package cn.lingyangwl.framework.database.flyway;

import cn.lingyangwl.framework.core.constant.LyCoreConstants;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;

import java.io.File;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * Configuration properties for Flyway database migrations.
 *
 * @author shenguangyang
 */
@Data
@ConfigurationProperties(prefix = LyCoreConstants.PROPERTIES_PRE_NO_POINT)
public class MyFlywayProperties {
	private List<Properties> flyways = Collections.emptyList();

	@Data
	public static class Properties {
		/**
		 * 指定数据源, 需要配合dynamic-datasource-spring-boot-starter依赖使用
		 */
		private String dataSource;
		/**
		 * Whether to enable flyway.
		 */
		private boolean enabled = true;

		/**
		 * Whether to fail if a location of migration scripts doesn't exist.
		 */
		private Boolean failOnMissingLocations;

		/**
		 * Locations of migrations scripts. Can contain the special "{vendor}" placeholder to
		 * use vendor-specific locations.
		 */
		private List<String> locations = new ArrayList<>(Collections.singletonList("classpath:db/migration"));

		/**
		 * Encoding of SQL migrations.
		 */
		private Charset encoding = StandardCharsets.UTF_8;

		/**
		 * Maximum number of retries when attempting to connect to the database.
		 */
		private int connectRetries;

		/**
		 * Maximum time between retries when attempting to connect to the database. If a
		 * duration suffix is not specified, seconds will be used.
		 */
		@DurationUnit(ChronoUnit.SECONDS)
		private Duration connectRetriesInterval;

		/**
		 * Maximum number of retries when trying to obtain a lock.
		 */
		private Integer lockRetryCount;

		/**
		 * Default schema name managed by Flyway (case-sensitive).
		 */
		private String defaultSchema;

		/**
		 * Scheme names managed by Flyway (case-sensitive).
		 */
		private List<String> schemas = new ArrayList<>();

		/**
		 * Whether Flyway should attempt to create the schemas specified in the schemas
		 * property.
		 */
		private Boolean createSchemas = true;

		/**
		 * Name of the schema history table that will be used by Flyway.
		 */
		private String table = "flyway_schema_history";

		/**
		 * Tablespace in which the schema history table is created. Ignored when using a
		 * database that does not support tablespaces. Defaults to the default tablespace of
		 * the connection used by Flyway.
		 */
		private String tablespace;

		/**
		 * Description to tag an existing schema with when applying a baseline.
		 */
		private String baselineDescription = "<< Flyway Baseline >>";

		/**
		 * Version to tag an existing schema with when executing baseline.
		 */
		private String baselineVersion = "1";

		/**
		 * Username recorded in the schema history table as having applied the migration.
		 */
		private String installedBy;

		/**
		 * Placeholders and their replacements to apply to sql migration scripts.
		 */
		private Map<String, String> placeholders = new HashMap<>();

		/**
		 * Prefix of placeholders in migration scripts.
		 */
		private String placeholderPrefix = "${";

		/**
		 * Suffix of placeholders in migration scripts.
		 */
		private String placeholderSuffix = "}";

		/**
		 * Separator of default placeholders.
		 */
		private String placeholderSeparator;

		/**
		 * Perform placeholder replacement in migration scripts.
		 */
		private Boolean placeholderReplacement = true;

		/**
		 * File name prefix for SQL migrations.
		 */
		private String sqlMigrationPrefix = "V";

		/**
		 * File name suffix for SQL migrations.
		 */
		private List<String> sqlMigrationSuffixes = new ArrayList<>(Collections.singleton(".sql"));

		/**
		 * File name separator for SQL migrations.
		 */
		private String sqlMigrationSeparator = "__";

		/**
		 * File name prefix for repeatable SQL migrations.
		 */
		private String repeatableSqlMigrationPrefix = "R";

		/**
		 * Target version up to which migrations should be considered.
		 */
		private String target;

		/**
		 * Login user of the database to migrate.
		 */
		private String user;

		/**
		 * Login password of the database to migrate.
		 */
		private String password;

		/**
		 * Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
		 */
		private String driverClassName;

		/**
		 * JDBC url of the database to migrate. If not set, the primary configured data source
		 * is used.
		 */
		private String url;

		/**
		 * SQL statements to execute to initialize a connection immediately after obtaining
		 * it.
		 */
		private List<String> initSqls = new ArrayList<>();

		/**
		 * Whether to automatically call baseline when migrating a non-empty schema.
		 */
		private Boolean baselineOnMigrate;

		/**
		 * Whether to disable cleaning of the database.
		 */
		private Boolean cleanDisabled;

		/**
		 * Whether to automatically call clean when a validation error occurs.
		 */
		private Boolean cleanOnValidationError;

		/**
		 * Whether to group all pending migrations together in the same transaction when
		 * applying them.
		 */
		private Boolean group;

		/**
		 * Whether to allow mixing transactional and non-transactional statements within the
		 * same migration.
		 */
		private Boolean mixed;

		/**
		 * Whether to allow migrations to be run out of order.
		 */
		private Boolean outOfOrder;

		/**
		 * Whether to skip default callbacks. If true, only custom callbacks are used.
		 */
		private Boolean skipDefaultCallbacks;

		/**
		 * Whether to skip default resolvers. If true, only custom resolvers are used.
		 */
		private Boolean skipDefaultResolvers;

		/**
		 * Whether to validate migrations and callbacks whose scripts do not obey the correct
		 * naming convention.
		 */
		private Boolean validateMigrationNaming = false;

		/**
		 * Whether to automatically call validate when performing a migration.
		 */
		private Boolean validateOnMigrate = true;

		/**
		 * Whether to batch SQL statements when executing them. Requires Flyway Teams.
		 */
		private Boolean batch;

		/**
		 * File to which the SQL statements of a migration dry run should be output. Requires
		 * Flyway Teams.
		 */
		private File dryRunOutput;

		/**
		 * Rules for the built-in error handling to override specific SQL states and error
		 * codes. Requires Flyway Teams.
		 */
		private String[] errorOverrides;

		/**
		 * Licence key for Flyway Teams.
		 */
		private String licenseKey;

		/**
		 * Whether to enable support for Oracle SQL*Plus commands. Requires Flyway Teams.
		 */
		private Boolean oracleSqlplus;

		/**
		 * Whether to issue a warning rather than an error when a not-yet-supported Oracle
		 * SQL*Plus statement is encountered. Requires Flyway Teams.
		 */
		private Boolean oracleSqlplusWarn;

		/**
		 * Whether to stream SQL migrations when executing them. Requires Flyway Teams.
		 */
		private Boolean stream;

		/**
		 * File name prefix for undo SQL migrations. Requires Flyway Teams.
		 */
		private String undoSqlMigrationPrefix;

		/**
		 * Migrations that Flyway should consider when migrating or undoing. When empty all
		 * available migrations are considered. Requires Flyway Teams.
		 */
		private String[] cherryPick;

		/**
		 * Properties to pass to the JDBC driver. Requires Flyway Teams.
		 */
		private Map<String, String> jdbcProperties = new HashMap<>();

		/**
		 * Path of the Kerberos config file. Requires Flyway Teams.
		 */
		private String kerberosConfigFile;

		/**
		 * Path of the Oracle Kerberos cache file. Requires Flyway Teams.
		 */
		private String oracleKerberosCacheFile;

		/**
		 * Location of the Oracle Wallet, used to sign-in to the database automatically.
		 * Requires Flyway Teams.
		 */
		private String oracleWalletLocation;

		/**
		 * Whether Flyway should output a table with the results of queries when executing
		 * migrations. Requires Flyway Teams.
		 */
		private Boolean outputQueryResults;

		/**
		 * Path to the SQL Server Kerberos login file. Requires Flyway Teams.
		 */
		private String sqlServerKerberosLoginFile;

		/**
		 * Whether Flyway should skip executing the contents of the migrations and only update
		 * the schema history table. Requires Flyway teams.
		 */
		private Boolean skipExecutingMigrations;

		/**
		 * Ignore migrations that match this comma-separated list of patterns when validating
		 * migrations. Requires Flyway Teams.
		 */
		private List<String> ignoreMigrationPatterns;

		/**
		 * Whether to attempt to automatically detect SQL migration file encoding. Requires
		 * Flyway Teams.
		 */
		private Boolean detectEncoding;

		/**
		 * Filename prefix for baseline migrations. Requires Flyway Teams.
		 */
		private String baselineMigrationPrefix;

		/**
		 * Prefix of placeholders in migration scripts.
		 */
		private String scriptPlaceholderPrefix;

		/**
		 * Suffix of placeholders in migration scripts.
		 */
		private String scriptPlaceholderSuffix;
	}

}
